home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / PROG_TOO / C027B.ZIP / TOP / FUNC.C < prev    next >
Text File  |  1990-03-30  |  5KB  |  217 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Tony Andrews
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  */
  11. #include "top.h"
  12.  
  13. BLOCK    *fhead;        /* head of the current function */
  14.  
  15. /*
  16.  * dofunc() - process one function
  17.  *
  18.  * Returns FALSE on end of file
  19.  */
  20. bool
  21. dofunc()
  22. {
  23.     BLOCK    *getfunc();
  24.  
  25. #ifdef    DEBUG
  26.     if (debug)
  27.         fprintf(stderr, "dofunc() - calling getfunc()\n");
  28. #endif
  29.     if ((fhead = getfunc()) == NULL)
  30.         return FALSE;
  31.  
  32.     /*
  33.      * Process the function we just read
  34.      */
  35.     bopt(fhead);    /* perform branch optimization (must be done first) */
  36.  
  37.     if (do_dflow)
  38.         rhealth(fhead);    /* perform live/dead register analysis */
  39.  
  40.     if (do_peep)
  41.         peep(fhead);    /* peephole optimizations */
  42.  
  43.     /*
  44.      * Now dump out the modified tree
  45.      */
  46. #ifdef    DEBUG
  47.     if (debug)
  48.         fprintf(stderr, "dofunc() - calling putfunc()\n");
  49. #endif
  50.     putfunc(fhead);
  51.  
  52. #ifdef    DEBUG
  53.     if (debug)
  54.         fprintf(stderr, "dofunc() - calling freesym()\n");
  55. #endif
  56.     freesym();        /* free the symbol table */
  57.  
  58.     return TRUE;
  59. }
  60.  
  61. static    bool    saw_eof = FALSE;
  62.  
  63. /*
  64.  * getfunc() - get a function and return a pointer to its starting block
  65.  *
  66.  * Returns NULL on end of file.
  67.  */
  68. BLOCK *
  69. getfunc()
  70. {
  71.     register BLOCK    *head;    /* starting block for this function */
  72.     register BLOCK    *cb;    /* the block we're currently reading */
  73.     register BLOCK    *ob;    /* the last block we read */
  74.  
  75.     if (saw_eof)
  76.         return NULL;
  77.  
  78.     head = NULL;
  79.  
  80.     /*
  81.      * Starting a global function
  82.      */
  83.     if (strcmp(t_op, ".globl") == 0) {
  84.         /*
  85.          * Enter the symbol and mark it global.
  86.          */
  87.         head = mksym(t_arg);
  88.         head->flags |= B_GLOBAL;
  89.     
  90.         readline();
  91.     }
  92.  
  93.     ob = NULL;
  94.  
  95.     for (;;) {
  96.         if (ob == NULL) {
  97.             if (t_lab[0] != '_') {
  98.                 fprintf(stderr, "top: expected function label\n");
  99.                 exit(1);
  100.             }
  101.             if (head == NULL)
  102.                 head = mksym(t_lab);
  103.  
  104.         } else if (t_lab[0] == '\0') {
  105.             fprintf(stderr, "top: expected block label\n");
  106.             exit(1);
  107.         }
  108.  
  109.         if ((cb = getsym(t_lab)) == NULL)
  110.             cb = mksym(t_lab);
  111.  
  112.         /*
  113.          * The last block falls through to this one.
  114.          */
  115.         if (ob != NULL) {
  116.             ob->chain = cb;
  117.             ob->next = cb;
  118.             ob->bfall = cb;
  119.         }
  120.  
  121.         t_lab[0] = '\0';
  122.  
  123.         /*
  124.          * Now read lines until we hit a new block or another
  125.          * function.
  126.          */
  127.         for (;;) {
  128.             /*
  129.              * If we see a global, we're done with the function
  130.              */
  131.             if (strcmp(t_op, ".globl") == 0)
  132.                 return head;
  133.             /*
  134.              * If we see a function label, we're done too.
  135.              */
  136.             if (t_lab[0] == '_')
  137.                 return head;
  138.             /*
  139.              * If we see any other label, we're done with the block.
  140.              */
  141.             if (t_lab[0])
  142.                 break;
  143.  
  144.             addinst(cb, t_op, t_arg);
  145.  
  146.             /*
  147.              * If we're at EOF, note the we've hit the end of
  148.              * file, but return the function we just read.
  149.              */
  150.             if (!readline()) {
  151.                 saw_eof = TRUE;
  152.                 return head;
  153.             }
  154.         }
  155.         ob = cb;
  156.     }
  157. }
  158.  
  159. /*
  160.  * putfunc(sb) - print out the function starting at block 'sb'
  161.  *
  162.  * The 'next' pointers determine the order in which things are placed
  163.  * in the file. Branch instructions have been removed so they need to
  164.  * be replaced here on output. Conditional branches are generated if
  165.  * indicated (by non-null 'bcond'). Unconditional branches are generated
  166.  * at the end of a block if it's "fall through" block isn't going to
  167.  * be the next thing in the file.
  168.  */
  169. putfunc(sb)
  170. register BLOCK    *sb;
  171. {
  172.     register BLOCK    *cb;
  173.     register INST    *ci;
  174.  
  175.     fprintf(ofp, "*\n");
  176.     fprintf(ofp, "* %s\n", sb->name);
  177.     fprintf(ofp, "*\n");
  178.     fprintf(ofp, "\t.text\n");
  179.  
  180.     for (cb = sb; cb != NULL ;cb = cb->next) {
  181.         if (cb->flags & B_GLOBAL)
  182.             fprintf(ofp, "\t.globl\t%s\n", cb->name);
  183.  
  184.         if (*cb->name == '_')
  185.             fprintf(ofp, "%s:\n", cb->name);
  186.  
  187.         else if (cb->flags & B_LABEL)
  188.             fprintf(ofp, "%s:\n", cb->name);
  189. #ifdef    DEBUG
  190.         if (debug) {
  191.             fprintf(ofp, "*\n");
  192.             fprintf(ofp, "* %s, ref:%04x  set:%04x\n",
  193.                 cb->name, cb->rref, cb->rset);
  194.             fprintf(ofp, "*\n");
  195.         }
  196. #endif
  197.  
  198.         for (ci = cb->first; ci != NULL ;ci = ci->next)
  199.             putinst(ci);
  200.         /*
  201.          * If there's a conditional branch, put out the
  202.          * appropriate instruction for it.
  203.          */
  204.         if (cb->bcond != NULL && cb->bcode >= 0)
  205.             fprintf(ofp, "\t%s\t%s\n",
  206.                 opnames[cb->bcode], cb->bcond->name);
  207.         /*
  208.          * If there's a "fall through" label, and the destination
  209.          * block doesn't come next, put out a branch.
  210.          */
  211.         if (cb->bfall != NULL && cb->bfall != cb->next) {
  212.             s_badd++;
  213.             fprintf(ofp, "\tbra\t%s\n", cb->bfall->name);
  214.         }
  215.     }
  216. }
  217.